#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<iostream>
#include<pthread.h>
#include<vector>
#include<queue>

using namespace std;

//线程池的实现
//

#define MAX_SIZE 5

template<class T>
class BlockQueue{
  //线程的安全队列
  private:
    queue<T> _q;
    int _capacity;
    pthread_mutex_t _mutex;
    pthread_cond_t _cond_pro;   
    pthread_cond_t _cond_con;
  public:
    BlockQueue(int capacity = MAX_SIZE):_capacity(capacity)
  {
    pthread_mutex_init(&_mutex, NULL);
    pthread_cond_init(&_cond_pro,NULL);
    pthread_cond_init(&_cond_con,NULL);
  }
    ~BlockQueue()
    {

      pthread_mutex_destroy(&_mutex);
      pthread_cond_destroy(&_cond_pro);
      pthread_cond_destroy(&_cond_con);
    }
    bool Push(const T& data)
    {
      pthread_mutex_lock(&_mutex);
      while(_q.size()==_capacity){
        //队列已满，阻塞生产者
        pthread_cond_wait(&_cond_pro,&_mutex);
      }
      _q.push(data);
      pthread_cond_signal(&_cond_con);  //唤醒消费者
      pthread_mutex_unlock(&_mutex);  //解锁
      return true;
    }
    bool Pop(T* data)
    {
      pthread_mutex_lock(&_mutex);
      while(_q.empty()){
        //队列为空，阻塞消费者
        pthread_cond_wait(&_cond_con,&_mutex);
      }
      *data=_q.front();
      _q.pop();
      pthread_cond_signal(&_cond_pro);  //唤醒生产者
      pthread_mutex_unlock(&_mutex);  //解锁
    }

};


//线程的安全任务队列
template<class T>
class ThreadTask{
  public:
    //等价于 typedef void (*Handle)(T) 定义一个函数类型
    //using Handler = std::function<void (T)>;
    typedef void(*Handler)(T) ;
    ThreadTask(){}
    ThreadTask(const T& data,Handler handler):_data(data),_handler(handler)
  {}
    void Start(){
      return _handler(_data);      //线程池中的数据只需要调用任务的Start接口即可完成使用传入的接口方式处理传入的数据
    }
  private:
    T _data; //数据
    Handler _handler;//数据的处理方式
};

//线程池的实现
template<class T>
class ThreadPool{
  private:
    int _thread_max;  //线程的最大数量
    BlockQueue<ThreadTask<T>> _queue;  //线程安全的任务队列
    vector<pthread_t> _tid; //保存线程 id
  private:
    //循环从任务队列中取出任务，调用任务的 Start 接口进行任务处理即可
    static void*thread_entry(void* arg)
    {
      //必须使用静态成员函数，因为线程的入口函数只能含有一个 void* 类型参数
      //而类中的非静态成员函数都会含有一个默认的参数 *this
      ThreadPool* pool=(ThreadPool*) arg;
      while(1){
        ThreadTask<T> task;
        pool->_queue.Pop(&task); //取出一个任务
        task.Start();  //调用任务的处理函数即可
      }
      return NULL;
    }

  public:
    //线程池的构造函数用来实现线程的创建
    ThreadPool(int thread_max,int queue_max):_thread_max(thread_max),_queue(queue_max)
  {
    int ret;
    pthread_t tid;
    for(int i=0;i<thread_max;++i){
      ret=pthread_create(&tid,NULL,thread_entry,this);
      if(ret!=0){
        perror("pthread_create error!\n");
        exit(-1);
      } 
    }
  }
    //任务的入队操作
    bool Push(ThreadTask<T>& task)
    {
      _queue.Push(task);
      return true;
    }
};

void print_test(int data)
{
  printf("%p threa,run data: %d\n",pthread_self(),data);
  sleep((data%3)+1);
}
int main()
{
  ThreadPool<int> pool(5,10); //5个线程 10个任务节点
  for(int i=0;i<10;++i){
    ThreadTask<int> task(i,print_test);
    pool.Push(task);
  }

  while(1) sleep(5);
  
  return 0;
}


